PopUp Hyper
Volume Number: 4
Issue Number: 5
Column Tag: Hyper
hat™ PopUpMenus in HyperTalk 
By Joseph Bergin, Professor, Marist College, NY
When Hypercard first appeared it wasn’t possible to include user defined menus
in your stacks. While waiting for my Hypercard developers kit to arrive from APDA
I decided to experiment and to see what could be done without resorting to XFCN’s and
XCMD’s. The result of my early trials is shown in Figure 1. It looks similar to a menu
bar except that I placed it on the top of a “card” instead of the top of the window.
Actually what you see is a collection of invisible labeled buttons drawn across the top
of a card and not an actual menu bar.
In Smalltalk a popup menu is a menu selection device which appears (pops up)
when you click the mouse button on certain screen areas. These areas do not need to be
anywhere special, and they do not need to be labeled. You select an option by clicking
(not releasing) on one of the choices. For example the main control window pops up
when you click on the background outside of any window. Another difference between
Apple’s pull down menus and Smalltalk’s popups is the fact that popups may stay on the
desktop while you work until you actually dismiss them, usually by taking some menu
choice. This is similar to Apple’s new tear off menus that made their appearance in
Hypercard.
Fig 1.
When you click on one of these buttons a “Popup Menu” appears. If we click on
the “Apple” we get Figure 2. This popup is actually a field. Clicking on the Apple only
made it appear. As you can see it has four choices presented to the user. If the user
clicks on one of these the corresponding action will be taken and the popup will
disappear. If you don’t take an action the popup will just sit there while you do other
things. The popup will also disappear if you move the browser (cursor) into the
window and then move it out again without clicking. This just “dismisses” the popup.
Fig. 2 The HyperCard PopUpMenu
The purpose of popup menus is to provide for those situations in which you want
to provide a lot of options for your user but you don’t want to clutter up the cards
and/or backgrounds with a lot of buttons which add visual “noise” to the interface.
The options may be clustered together in groups and each group may be provided with a
single button to call up a popup with the associated choices. There are a number of
other solutions to this problem but if used wisely popup menus can be a valuable
addition to your Hypercard toolkit.
Actually, what I learned about HyperTalk along the way to creating these popups
was as valuable as the popups themselves. In order to make the creation of popups
easier I decided to automate the process. This made it unnecessary for me to remember
all of the steps that were needed in creation of a popup and its associated button, field,
and scripts. The solution was to create a command which creates new popups, but it
does so by having a script that writes scripts.
In the Unix world a program which writes other programs is a fairly standard
item (YACC and LEX for example) but they seem to be less used in other environments.
They are an important development tool, however, and quite easy to do in Hypercard.
The necessary scripts
Before we get into the operation of the ScriptWriter we should look first at the
scripts that are needed for the popups to operate correctly.
Suppose that we want to have a popup called “Apple” and we want it to look like
the first example in this article. We will need a background button called “Apple”
which, when clicked shows a background field called “Apple.” The script to do this is
simply
on mouseUp
show bkgnd field Apple -- at the clickLoc
-- remove the dashes above for a
--nice effect
end mouseUp
which belongs in the script of the “ apple” button.
Next we need the background field called by the same name, “Apple.” It has a
script to hide itself ( target) and one to select and execute the required user choice,
which here is done on mouseUp. It also has a special action command (“ apple1”,
“ apple2”, etc.) for each visible line of the field. You may have more action commands
than visible lines if you like but they won’t be usable. You can also add new action
commands at any time by editing the script, and increasing the number of visible lines
in the field and all will be well. Note though that the lockText property of the field
will have to be set to true so that Hypercard will be able to recognize a click in the
field. The required scripts for this field are:
on mouseLeave
hide the target
end mouseLeave
on mouseUp
selectChoice
end mouseUp
on apple1
open MacWrite
end apple1
on apple2
open MacPaint
end apple2
on apple3
open MacProject
end apple3
on apple4
doMenu “Quit Hypercard”
end apple4
Recall that the second choice on the “Apple menu” was to open Mac Paint. This
will happen when we execute the command apple2. The command selectChoice decides
that the mouseup happened on line 2 of the popup and dispatched the command apple2.
The small scripts appleN can contain anything that you like. They can show or
hide fields or buttons. They can paint. They can do menu commands or open files or
stacks. They should be kept short, though, perhaps by defining new commands that
they call.
After the field was created and the scripts put into it the lockText was set to false
so that its contents could be edited. Then a line was entered into the field for each
possible choice, indicating what the choice is. Then the lockText was set to true.
The script for selectChoice is either in the stack script or, perhaps, in the
script of the Home Card. This command is called when the user mouses down in a
popup. It first computes the line number on which the user clicked the mouse and then
executes a command whose name is the same as the name of the field which took the
click with the line number appended to it. Thus, if the user clicked on line 3
(selection 3) of a popup whose field was called Apple, this script would execute
command apple3, which was shown above.
on selectChoice --used by popups
put the short name of the target into theName
get the rect of the target --field clicked in
put item 2 of it into top --top of the rect
get the textHeight of the target
put it into size --how big each line is
put ((item 2 of the clickLoc) - top + size)
div size into lineNumber
send ( theName&linenumber) to target
-- executes the required command
end selectChoice
How to create popups
Since there is so much to do and type for popups it would be nice to automate
their creation. The following shows how. It assumes that you want your popup buttons
and fields that define the popup to be part of the background, and that if you create a
new card from the background you will want the popup to look and behave the same in
the new card. None of these assumptions are required and you might experiment to
discover the effect of doing it differently. That would require modifying the script for
the command “newPopup” which is described next.
To create a new popup called Apple, with four options, in a stack that contains all
of these scripts you just type
newPopup Apple,4
into the message window and the button and field will be created and the required
scripts will be put into them. You will then need to resize and place the field in the
card, type your menu options into it, lock its text, and edit the action commands to give
the effect that you want. The action command skeletons
on Apple1
end Apple1
etc. will be created for you however.
The script that does all this work is shown below. It uses three other commands
which are shown later. First, newPopup, which has two parameters, theName and
theNumber, locks the screen to speed things up, says that we want to do this stuff to
the background, and remembers the current tool so that it can be restored to the user
at the end. Next it calls the first auxiliary command to create the button which will
bring up the popup. Then the next command creates the popup itself, and the last
command in the group adds a script segment to the background so that new Card
operations will perform as suggested above. Finally the user’s state is restored and
the screen unlocked. [I have done some modifications to the script which will allow a
windoid type menu that can be draged around. The original script is intact; there are
comments how to modify it. The modifications are in italics. -HyperEd]
on newPopup theName,theNumber
---- add next line for watch cursor HyperEd
-- set cursor to 4
----
set lockScreen to true
set editBkgnd to true
put the tool into oldTool
doNewButton theName
---- add this line HyperEd
-- doNewBtnClose theName
----
doNewField theName, theNumber
set editBkgnd to false
fixBkgnd theName
choose oldTool
set lockscreen to false
---- Return to normal cursor HyperEd
-- set cursor to 1
----
end newPopup
[The next section puts in the button for the close box. HyperEd]
--on doNewBtnClose theName -- This whole procedure HyperEd
-- set editBkgnd to true
doMenu “New Button”
set name of bkgnd button “New Button” to “close”
set style of bkgnd button close to checkbox
set autoHilite of bkgnd button close to true
set showname of bkgnd button close to false
set rect of bkgnd button close to 206,73,226,90
put “on mouseup” into newScript
put “hide bkgnd field” && theName into line 2 of newScript
put “hide bkgnd btn close” into line 3 of newScript
put “set hilite of me to false” into line 4 of newScript
put “set hilite of bkgnd btn” && theName && “to false”
into line 5 of newScript
put “end mouseUp” into line 6 of newScript
set script of bkgnd button close to newScript
--end doNewBtnClose
Next we need to examine the three auxiliary commands that newPopup used. The
doNewButton command is the easiest and it illustrates the technique of scripts which
write scripts. The first line of it just creates a new button. It doesn’t say background
button, but it will be because of the fact that it is called after setting edit bkgnd to true.
The next five commands just set some properties of the new button to something
convenient. Note that the New Button menu command should set the new button’s name
to New Button. If it doesn’t, you will need a script called newButton which just sets
the name of “the target” to “New Button”. We will need to do a similar thing for new
fields also.
on doNewButton theName
-- set editBkgnd to true
doMenu “New Button”
set name of bkgnd button “New Button” to theName
---- change next line to shadow HyperEd
set style of bkgnd button theName to transparent
----
---- change next line to false HyperEd
set autoHilite of bkgnd button theName to true
----
set showname of bkgnd button theName to true
set rect of bkgnd button theName to 206,70,306,92
put “on mouseup” into newScript
put “show bkgnd field” && theName into line 2 of newScript
---- add these three lines HyperEd
-- put “show bkgnd btn close” into line 3 of newScript
-- put “set hilite of bkgnd btn” && theName && “to true”
-- into line 4 of newScript
----
put “end mouseUp” into line 5 of newScript
--- This Section added take away “--” HyperEd
-- put “on mousestilldown” into line 8 of newScript
-- put “set lockscreen to true” into line 9 of newScript
-- put “if the visible of bkgnd field” && theName && “is true then”
-- into line 10 of newScript
-- put “set the loc of me to the mouseloc” into line 11 of
newScript
-- put “set the loc of bkgnd btn close to the mouseh -36, the
mousev”
-- into line 12 of newScript
-- put “set the loc of bkgnd field” && theName && “to the mouseh,
the mousev+93”
-- into line 13 of newScript
-- put “end if” into line 14 of newScript
-- put “set lockscreen to false” into line 15 of newScript
-- put “end mousestilldown” into line 16 of newScript
---- End Section HyperEd
set script of bkgnd button theName to newScript
---- added HyperEd
-- set hilite of bkgnd btn theName to true